0.关键字
        /*
         与声明有关的关键字
         class    deinit    enum    extension
         func    import    init    internal
         let    operator    private    protocol
         public    static    struct    subscript
         typealias    var
         与语句有关的关键字
         break    case    continue    default
         do    else    fallthrough    for
         if    in    return    switch
         where    while
         表达式和类型关键字
         as    dynamicType    false    is
         nil    self    Self    super
         true    _COLUMN_    _FILE_    _FUNCTION_
         _LINE_
         在特定上下文中使用的关键字
         associativity    convenience    dynamic    didSet
         final    get    infix    inout
         lazy    left    mutating    none
         nonmutating    optional    override    postfix
         precedence    prefix    Protocol    required
         right    set    Type    unowned
         weak    willSet
         */




一、可选(Optionals): 
可选?  强制解析!




二、函数(func)
无参数无返回
func sitename(){
1.多参数多返回
func minMax(array: [Int],name:String) -> (min: Int, max: Int)? {

if let bounds = minMax(array: [8, -6, 2, 109, 3, 71],name:"name") {
  print("最小值为 \(bounds.min)，组大值为 \(bounds.max)")}

2.可变参数
func vari<N>(members: N...){
vari(members: 1)
vari(members: "Google", "Baidu", "Runoob")

3.常量，变量及 I/O 参数
改变入参
func swapTwoInts(_ a: inout Int, _ b: inout Int) {

var x = 1;var y = 5
swapTwoInts(&x, &y)
print("x 现在的值 \(x), y 现在的值 \(y)")

4.函数类型及使用
a.addition
func sum(a: Int, b: Int) -> Int {
return a + b}
var addition: (Int, Int) -> Int = sum//addition函数别名?
print("输出结果: \(addition(40, 89))")

b.addition作为参数
func another(addition: (Int, Int) -> Int, a: Int, b: Int) {//把addition写到里面去,作为参数
print("输出结果: \(addition(a, b))")}
another(addition: sum, a: 10, b: 20)




三、闭包(Closures)
1.逃逸闭包
加@escaping
func startRequest(callBack:@escaping ()->Void ) {
    DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 1) { 
        callBack()
    }
}

2.多参数
let divide = {(val1: Int, val2: Int) -> Int in
return val1 / val2}
let result = divide(200, 20)

//3.闭包表达式
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
//不使用闭包
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
//Swift 标准库提供了sort函数，会根据您提供的基于输出类型排序的闭包函数将已知类型数组中的值进行排序。
var reversed = sort(names, backwards)
println(reversed)


//使用闭包
//闭包的函数体部分由关键字in引入。 该关键字表示闭包的参数和返回值类型定义已经完成，闭包函数体即将开始。
reversed = sort(names, {(s1: String, s2: String) -> Bool in
return s1 > s2
})

//根据上下文推断类型
reversed = sort(names, {s1, s2 in return s1 > s2})


//4单表达式闭包隐式返回
//如果闭包体只有一个表达式, 那么return关键字可以省略
reversed = sort(names, {s1, s2 in s1 > s2})

//5 参数名称缩写
//$0和$1表示闭包中第一个和第二个String类型的参数。
reversed = sort(names, {$0 > $1})

//6 运算符函数
//Swift 的String类型定义了关于大于号 (>) 的字符串实现
reversed = sort(names, >)

//7. 尾随闭包
//如果您需要将一个很长的闭包表达式(以至于不能在一行中进行书写时)作为最后一个参数传递给函数，
可以使用尾随闭包来增强函数的可读性。 尾随闭包是一个书写在函数括号之后的闭包表达式，
函数支持将其作为最后一个参数调用。
reversed = sort(names){$0 > $1}
println(reversed)

//4.捕获值
//函数外部参数累加???
 func makeIncrementor(forIncrement amount: Int) -> () -> Int {
            var runningTotal = 0
            print("\(amount):\(runningTotal)")//10:0只执行一次
            func incrementor() -> Int {
                runningTotal += amount
                print("\(amount):\(runningTotal)")//10:10;10:20;10:30
                return runningTotal
            }
            return incrementor
        }
        let incrementByTen = makeIncrementor(forIncrement: 10)
        // 返回的值为10
        print(incrementByTen())
        // 返回的值为20
        print(incrementByTen())
        // 返回的值为30
        print(incrementByTen())
/*
一个函数makeIncrementor ，它有一个Int型的参数amout, 并且它有一个外部参数名字forIncremet，
意味着你调用的时候，必须使用这个外部名字。返回值是一个()-> Int的函数。
函数题内，声明了变量runningTotal 和一个函数incrementor。
incrementor函数并没有获取任何参数，但是在函数体内访问了runningTotal和amount变量。
这是因为其通过捕获在包含它的函数体内已经存在的runningTotal和amount变量而实现。
由于没有修改amount变量，incrementor实际上捕获并存储了该变量的一个副本，
而该副本随着incrementor一同被存储。
所以我们调用这个函数时会累加：
*/
//runningTotal的值会一直叠加


//5.闭包是引用类型
/*
上面的例子中，incrementByTen是常量，但是这些常量指向的闭包仍然可以增加其捕获的变量值。
这是因为函数和闭包都是引用类型。
无论您将函数/闭包赋值给一个常量还是变量，您实际上都是将常量/变量的值设置为对应函数/闭包的引用。 
上面的例子中，incrementByTen指向闭包的引用是一个常量，而并非闭包内容本身。
这也意味着如果您将闭包赋值给了两个不同的常量/变量，两个值都会指向同一个闭包：
*/
 incrementByTen()
let alsoIncrementByTen = incrementByTen
// 返回的值也为50,不为0
print(alsoIncrementByTen())




四、枚举
//非数值、初始值为0
//1.一元枚举
        enum DaysofaWeek {
            case Sunday
            case Monday
            case TUESDAY
            case WEDNESDAY
            case THURSDAY
            case FRIDAY
            case Saturday
        }
        var weekDay = DaysofaWeek.THURSDAY
        weekDay = .THURSDAY
        switch weekDay
        {
        case .Sunday:
//2.二元枚举
       enum Student{
            case Name(String)
            case Mark(Int,Int,Int)
        }
        var studDetails = Student.Name("Runoob","a")
        var studMarks = Student.Mark(98,97,95)
        switch studMarks {
        case .Name(let studName):
            print("学生的名字是: \(studName)。")
        case .Mark(let Mark1, let Mark2, let Mark3):
            print("学生的成绩是: \(Mark1),\(Mark2),\(Mark3)。")
        }




五、结构体
 struct MarksStruct {//关键字struct
            var mark: Int
            init(mark: Int) {
                self.mark = mark
            }
        }
        var aStruct = MarksStruct(mark: 98)
        var bStruct = aStruct // aStruct 和 bStruct 是使用相同值的结构体！,copy了一份
        bStruct.mark = 97//通过.调用
        print(aStruct.mark) // 98
        print(bStruct.mark) // 97




六、类
    class SampleClass: Equatable {
            let myProperty: String
            init(s: String) {
                myProperty = s
            }
        }
        func == (lhs: SampleClass, rhs: SampleClass) -> Bool {
            return lhs.myProperty == rhs.myProperty
        }
        let spClass1 = SampleClass(s: "Hello")
        let spClass2 = SampleClass(s: "Hello")
        if spClass1 === spClass2 {// false
            print("引用相同的类实例 \(spClass1)")
        }
        if spClass1 !== spClass2 {// true
            print("引用不相同的类实例 \(spClass2)")
        }




七、属性
        struct Number
        {
            var i: Int//n没初值不能用let
            var digits: Float
            let pi = 3.1415
        }
        var n = Number(i:1,digits: 12345)
        n.digits = 67
        print("\(n.digits)")
        print("\(n.pi)")
//        n.pi = 67//let不能重新赋值
//        n.pi += 1//let不能做运算
        //高精度能赋值低精度,低精度不能赋值高精度
        n.digits = 67.6
        n.i=2.2//报错

//2.延迟存储属性
//当第一次被调用的时候才会计算其初始值的属性。
 lazy var no = number() // `var` 关键字是必须的

//3.实例化变量
        class sample {
            var no1 = 0.0, no2 = 0.0
            var length = 300.0, breadth = 150.0
            var middle: (Double, Double) {
                get{//重新get
                    return (length / 2, breadth / 2)
                }
                set(axis){//重新set
                    no1 = axis.0 - (length / 2)
                    no2 = axis.1 - (breadth / 2)
                }
            }
        }
        var result = sample()
        print(result.middle)//调get
        result.middle = (0.0, 10.0)//调set
        print(result.no1)
        print(result.no2)




八、方法
1.外部参数
class multiplication {
var count: Int = 0
func incrementBy(first no1: Int, no2: Int) {
count = no1 * no2
print(count)
}
}
let counter = multiplication()
counter.incrementBy(first: 800, no2: 3)//first为外部参数供外部使用,只能用first.不能用no1
counter.incrementBy(first: 100, no2: 5)
counter.incrementBy(first: 15000, no2: 3)

2.slef属性与循环引用
函数内使用self属性,等会引起循环引用

3.在实例方法中修改值类型
修改值类型mutating
        struct area {
            var length = 1
            var breadth = 1

            func area() -> Int {
                return length * breadth
            }
            mutating func scaleBy(res: Int) {//修改值类型mutating
                length *= res
                self.breadth *= res//也可以用self
                print(length)
                print(breadth)
            }
        }
        var val = area(length: 3, breadth: 5)
        val.scaleBy(res: 3)
        val.scaleBy(res: 30)
        val.scaleBy(res: 300)

//4.继承




九、下标脚本
//1.下标脚本 可以定义在类（Class）、结构体（structure）和枚举（enumeration）
struct Matrix {
    let rows: Int, columns: Int
    var print: [Double]//重写
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
     print = Array(repeating: 0.0, count: rows * columns)
    }
    subscript(row:Int)->Int{
        return row
    }
    subscript(row: Int, column: Int) -> Double {
        get {
            return print[(row * columns) + column]
        }
        set {
            print[(row * columns) + column] = newValue
        }
    }
}
// 创建了一个新的 3 行 3 列的Matrix实例
var mat = Matrix(rows: 3, columns: 3)
print(mat)
// 通过下标脚本设置值
mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0
print(mat)
// 通过下标脚本获取值
print("\(mat[0,0])")
print("\(mat[0,1])")
print("\(mat[1,0])")
print("\(mat[1,1])")
print("\(mat[1])")
print("\(mat[2])")
print("\(mat[3])")




十、继承
1.重写（overriding）
如果你在重写属性中提供了 setter，那么你也一定要提供getter。
如果你不想在重写版本中的getter里修改继承来的属性值，
你可以直接通过super.someProperty来返回继承来的值，其中someProperty是你要重写的属性的名字。
class Circle {
    var radius = 12.5
    var area: String {
        return "矩形半径 \(radius) "
    }
}
// 继承超类 Circle
class Rectangle: Circle {
    var print = 7
    override var area: String {//overriding继承
        return super.area + " ，但现在被重写为 \(print)"//不想重新getter方法,用super.area
    }
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

//属性观察器,你不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器。
class Square: Rectangle {
    override var radius: Double {
        didSet {//属性观察器
            print = Int(radius/5.0)+1
        }
    }
}
let sq = Square()
sq.radius = 100.0
print("半径: \(sq.area)")

2.防止重写(final)
final class Circle {//类防止重写
    final var radius = 12.5//属性防止重写
        var area: String {
        return "矩形半径为 \(radius) "
    }
}
class Rectangle: Circle {
    var print = 7
    override var radius: Float {
        return super.radius + " ，但现在被重写为 \(print)"
    }
    override var area: String {
        return super.area + " ，但现在被重写为 \(print)"
    }
}




十一、构造过程 
1.构造器
init()
2.默认属性
自动推到属性类型
3.内部和外部参数名
默认生成和内部同名的外部名
4.没有外部名称参数
可以使用下划线“_”来显示描述它的外部名。
5.可选属性类型
"?"逻辑上允许取值为空的存储型属性;当存储属性声明为可选时，将自动初始化为空 nil。
6.构造过程中修改常量属性
可在构造过程修改没赋值的常量属性
7.默认构造器
8.struct的逐一成员构造器
class没有
9.指定构造器和便利构造器convenience
每个类至少有一个指定构造器
10.构造器的继承和重载
子类不会默认继承父类的构造器,父类的构造器仅在确定和安全的情况下被继承。
当你重写一个父类指定构造器时，你需要写override修饰符。
11.可失败构造器
'init?'

class Rectangle {
    let length: Double?//5.可选属性类型
    var breadth = 12// 2.设置默认值
    var area: Double

    init(frombreadth breadth: Double,fromBreadth breadth: Double) {//1.构造器,3.构造参数
        breadth = breadth * 10
    }
    init(frombre bre: Double) {//6.可在构造过程修改没赋值的常量属性
        length = bre * 30
    }

    init(_ area: Double) {//4.不提供外部使用
        length = area
    }
    init?( length: Double,breadth: Double,area: Double) {//11.可失败构造器
        length = length
        breadth =breadth
    }
}

let a=Rectangle(frombreadth:1.2,fromBreadth:33.22)//3.外部使用的参数
let b=Rectangle()//7.默认构造器
var a = ShoppingListItem(name:"",quantity:1,purchased:false)//8.struct才有逐一构造器.class没有

class subClass : Rectangle {
    var no2 : Int
    init(no1 : Int, no2 : Int) {
        self.no2 = no2
        super.init(no1:no1)
    }
    // 9.便利构造器convenience只需要一个参数
    override convenience init(_ area: Double) {//10.默认不继承,确定和安全下才继承,需加override
        length = area
    }
}

//枚举可失败的构造器
      enum TemperatureUnit {
            // 开尔文，摄氏，华氏
            case Kelvin, Celsius, Fahrenheit
            init?(symbol: Character) {
                switch symbol {
                case "K":
                    self = .Kelvin
                case "C":
                    self = .Celsius
                case "F":
                    self = .Fahrenheit
                default:
                    return nil
                }
            }
        }
        let fahrenheitUnit = TemperatureUnit(symbol: "F")
        if fahrenheitUnit != nil {
            print("这是一个已定义的温度单位，所以初始化成功。")
        }
        let unknownUnit = TemperatureUnit(symbol: "X")
        if unknownUnit == nil {
            print("这不是一个已定义的温度单位，所以初始化失败。")
        }

//类的可失败构造器
        class StudRecord {
            let studname: String!
            init?(studname: String) {
                self.studname = studname
                if studname.count<1 { return nil }
            }
        }
        if let stname = StudRecord(studname: "失败构造器") {
            print("模块为 \(stname.studname)")
        }else{
            print("失败")
        }
        if let stname1 = StudRecord(studname: "") {
            print("模块为 \(stname1.studname)")
        }else{
            print("失败")
        }

19.覆盖一个可失败构造器
//可失败构造器不能覆盖非可失败构造器

20.也可用“!”代替“?”

十二、析构过程
deinit {

十三、可选链
1.可以用可选链检查并获取下标脚本的调用是否成功;但不能用可选链设置下标脚本
2.可以通过可选链接来调用返回可空值的方法，并且可以继续对可选值进行链接。

        class Person {
            var residence: Residence?//可选属性
        }
        // 定义了一个变量 rooms，它被初始化为一个Room[]类型的空数组
        class Residence {
            var rooms = [Room]()
            var numberOfRooms: Int {
                return rooms.count
            }
            subscript(i: Int) -> Room {
                return rooms[i]
            }
            func printNumberOfRooms() {
                print("房间号为 \(numberOfRooms)")
            }
            var address: Address?
        }
        // Room 定义一个name属性和一个设定room名的初始化器
        class Room {
            let name: String
            init(name: String) { self.name = name }
        }
        // 模型中的最终类叫做Address
        class Address {
            var buildingName: String?
            var buildingNumber: String?
            var street: String?
            func buildingIdentifier() -> String? {
                if (buildingName != nil) {//检查可选链
                    return buildingName
                } else if (buildingNumber != nil) {//检查可选链
                    return buildingNumber
                } else {
                    return nil
                }
            }
        }

        let john1 = Person()
        if let firstRoomName = john1.residence?[0].name {//检查并获取下标脚本
            print("第一个房间名 \(firstRoomName).")
        } else {
            print("无法检索到房间")
        }
        let john2 = Person()
        let johnsHouse = Residence()//创建赋值
        johnsHouse.rooms.append(Room(name: "客厅"))
        johnsHouse.rooms.append(Room(name: "厨房"))
        john2.residence = johnsHouse
        let johnsAddress = Address()
        johnsAddress.buildingName = "The Larches"
        johnsAddress.street = "Laurel Street"
        john2.residence!.address = johnsAddress
        if let johnsStreet = john2.residence?.address?.street {
            print("John 所在的街道是 \(johnsStreet)。")
        } else {
            print("无法检索到地址。 ")
        }

         let john = Person()
        if john.residence?.printNumberOfRooms() != nil {
            //可以通过可选链接来调用返回可空值的方法，并且可以继续对可选值进行链接。
            print("指定了房间号)")
        }  else {
            print("未指定房间号")
        }




十四、引用计数
1.用self会持用自身
2.解决循环引用:用弱引用带“?”
3.无主引用
4.闭包的无主引用
5.闭包的弱引用self要加“?”(不建议或“!”

class Student {
    let name: String
    var section: Marks?
    init(name: String) {
        self.name = name
    }
    deinit { print("\(name)") }
}
class Marks {
            let marks: Int
            weak var topic: Student?//弱引用带?
            unowned let stname: Student//无主引用
            init(marks: Int, stname: Student) {
                self.marks = marks
                self.stname = stname//用self会持有Student
            }
            deinit { print("学生的分数为 \(marks)") }
        }
        var module: Student?
        module = Student(name: "ARC")
        module!.section = Marks(marks: 98, stname: module!)
        print(module?.section?.stname)
        module = nil


         class HTMLElement {
            let name: String
            let text: String?
            lazy var asHTML: () -> String = {
                [unowned self] in//捕获的引用绝对不会置为nil，应该用无主引用，而不是弱引用。
                if let text = self.text {
                    return "<\(self.name)>\(text)</\(self.name)>"
                } else {
                    return "<\(self.name) />"
                }
                /*
                //弱引用
                [weak self] in
                if let text = self?.text {
                    return "<\(self?.name)>\(text)</\(self?.name)>"
                } else {
                    return "<\(self?.name) />"
                }*/
            }
            init(name: String, text: String? = nil) {
                self.name = name
                self.text = text
            }
            deinit {
                print("\(name) 被析构")
            }
        }
        //创建并打印HTMLElement实例
        var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
        print(paragraph!.asHTML())
        // HTMLElement实例将会被销毁，并能看到它的析构函数打印出的消息
        paragraph = nil





十五、类型转换
1.is 用于检测值的类型，as 用于转换类型。建议用as?不建议用as!

        class Subjects {
            var physics: String
            init(physics: String) {
                self.physics = physics
            }
        }
        class Chemistry: Subjects {
            var equations: String
            init(physics: String, equations: String) {
                self.equations = equations
                super.init(physics: physics)
            }
        }
        class Maths: Subjects {
            var formulae: String
            init(physics: String, formulae: String) {
                self.formulae = formulae
                super.init(physics: physics)
            }
        }
        let sa = [
            Chemistry(physics: "固体物理", equations: "赫兹"),
            Maths(physics: "流体动力学", formulae: "千兆赫")]
        var chemCount = 0
        var mathsCount = 0
        for item in sa {
            if item is Chemistry {
                print('1')
            }
            // 类型转换的条件形式
            if let show = item as? Chemistry {//转换类型
                print("化学主题是: '\(show.physics)', \(show.equations)")
                // 强制形式
            } else if let example = item as? Maths {
                print("数学主题是: '\(example.physics)',  \(example.formulae)")
            }
        }

2.Any和AnyObject的类型转换
AnyObject可以代表任何class类型的实例。
Any可以表示任何类型，包括方法类型（function types）。
        //any
        var exampleany = [Any]()
        exampleany.append(12)
        exampleany.append(3.14159)
        exampleany.append("Any 实例")
        exampleany.append(Chemistry(physics: "固体物理", equations: "兆赫"))
        for item2 in exampleany {
            switch item2 {
            case let someInt as Int:
                print("整型值为 \(someInt)")
            case let someDouble as Double where someDouble > 0:
                print("Pi 值为 \(someDouble)")
            case let someString as String:
                print("\(someString)")
            case let phy as Chemistry:
                print("主题 '\(phy.physics)', \(phy.equations)")
            default:
                print("None")
            }
        }
        
        // [AnyObject] 类型的数组
        let saprint: [AnyObject] = [
            Chemistry(physics: "固体物理", equations: "赫兹"),
            Maths(physics: "流体动力学", formulae: "千兆赫"),
            Chemistry(physics: "热物理学", equations: "分贝"),
            Maths(physics: "天体物理学", formulae: "兆赫"),
            Maths(physics: "微分方程", formulae: "余弦级数")]
        let samplechem = Chemistry(physics: "固体物理", equations: "赫兹")
        print("实例物理学是: \(samplechem.physics)")
        print("实例方程式: \(samplechem.equations)")
        let samplemaths = Maths(physics: "流体动力学", formulae: "千兆赫")
        print("实例物理学是: \(samplemaths.physics)")
        print("实例公式是: \(samplemaths.formulae)")



十六、扩展extension
扩展就是向一个已有的类、结构体或枚举类型添加新功能。
扩展可以对一个类型添加新的功能，但是不能重写已有的功能。

1.计算型
        extension Int {
            var add: Int {return self + 100 }
            var sub: Int { return self - 10 }
            var mul: Int { return self * 10 }
            var div: Int { return self / 5 }
        }
        let addition = 3.add

2.构造器
        extension mult {
            init(x: sum, y: diff) {
                _ = x.num1 + x.num2
                _ = y.no1 + y.no2
            }
        }
        let a = sum(num1: 100, num2: 200)

3.方法 
extension Int {
   func topics(summation: () -> ()) {
      for _ in 0..<self {
         summation() 
      }
   }
}  
        4.topics(summation: {
            print("扩展模块内")
        })

4.可变实例方法
extension Double {
   mutating func square() {//可变实例方法mutating 改变自身的值
      let pi = 3.1415
      self = pi * self * self
   }
}
var Trial1 = 3.3
Trial1.square()
print("圆的面积为: \(Trial1)")
Trial1.square()
print("圆的面积为: \(Trial1)")

5.扩展下标
extension Int {
   subscript(var multtable: Int) -> Int {
      var no1 = 1
      while multtable > 0 {
         no1 *= 10
         --multtable
      }
      return (self / no1) % 10
   }
}
print(12[0])

5.嵌套类型
extension Int {
   enum calc
   {
      case add
      case sub
      case mult
      case div
      case anything
   }
   var print: calc {
      switch self
      {
         case 0:
            return .add
         case 1:
            return .sub
         case 2:
            return .mult
         case 3:
            return .div
         default:
            return .anything
       }
   }
}
func result(numb: [Int]) {
   for i in numb {
      switch i.print {
         case .add:
            print(" 10 ")
          case .sub:
            print(" 20 ")
         case .mult:
         print(" 30 ")
         case .div:
         print(" 40 ")
         default:
         print(" 50 ")

      }
   }
}
result([0, 1, 2, 3, 4, 7])


十七、协议
protocol SomeProtocol {
    // 协议内容
}
struct SomeStructure: FirstProtocol, AnotherProtocol {
    // 结构体内容
}
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
    // 类的内容
}

2.协议属性,要声明{ get set }
protocol classa {
    var marks: Int { get set }
    var result: Bool { get }
    func attendance() -> String
    func markssecured() -> String

}
protocol classb: classa {
    var present: Bool { get set }
    var subject: String { get set }
    var stname: String { get set }
}

3.mutating可修改属性
protocol daysofaweek {
    mutating func show()
}

   enum days: daysofaweek {
            case sun, mon, tue, wed, thurs, fri, sat
            mutating func show() {//mutating可修改
                switch self {
                case .sun:
                    self = .mon
                    print("Sunday")
                case .mon:
                    self = .tue
                    print("Monday")
                case .tue:
                    self = .wed
                    print("Tuesday")
                case .wed:
                    self = .thurs
                    print("Wednesday")
                case .thurs:
                    self = .fri
                    print("Wednesday")
                case .fri:
                    self = .sat
                    print("Wednesday")
                case .sat:
                    self = .sun
                    print("Saturday")
                default:
                    print("NO Such Day")
                }
            }
        }
        var res = days.wed
        res.show()
        print(res)

4.遵守request的协议要加override
protocol tcpprotocol {
    init(no1: Int)
}

class mainClass {
    var no1: Int // 局部变量
    init(no1: Int) {
        self.no1 = no1 // 初始化
    }
}

class subClass: mainClass, tcpprotocol {
    var no2: Int
    init(no1: Int, no2 : Int) {
        self.no2 = no2
        super.init(no1:no1)
    }
    // 因为遵循协议，需要加上"required"; 因为继承自父类，需要加上"override"
    required override convenience init(no1: Int)  {
        self.init(no1:no1, no2:0)
    }
}
        let res = mainClass(no1: 20)
        let show = subClass(no1: 30, no2: 50)
        print("res is: \(res.no1)")
        print("res is: \(show.no1)")
        print("res is: \(show.no2)")

5.协议类型
//协议可以被当做类型来使用。
//协议：定义了生成随机数方法
protocol RandomNumberGenerator {
    func random() -> Double
}
class LinearCongruentialGenerator: RandomNumberGenerator {
            var lastRandom = 42.0
            let m = 139968.0
            let a = 3877.0
            let c = 29573.0
            func random() -> Double {
                //使用truncatingRemainder方法进行浮点数取余
                lastRandom = (lastRandom * a + c).truncatingRemainder(dividingBy: m)
                return lastRandom / m
            }
        }
        //Dice的generator属性，其类型是RandomNumberGenerator协议类型
        class Dice {
            let sides: Int
            let generator: RandomNumberGenerator    //协议作为属性
            
            //协议作为参数类型
            init(sides: Int, generator: RandomNumberGenerator) {
                self.sides = sides
                self.generator = generator
            }
            func roll() -> Int {
                return Int(generator.random() * Double(sides)) + 1
            }
        }
        var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
        for _ in 1...5 {
            print("Random dice roll is \(d6.roll())")
        }

6.专属继承
protocol ViewProperty: class, SomeInheritedProtocol {
    // 协议定义
    func printFrame() {
        print("this is not a view，cant print frame")
    }
}

extension SomeInheritedProtocol:ViewProperty{}//空扩展表示遵循协议

let things:[ViewProperty] = [view,customOject]//7.协议类型的集合
for thing in things{
    thing.printFrame()//调用协议
}

8.协议合成
protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}
//Person遵循两个协议
struct Person: Named, Aged {
    var name: String
    var age: Int
}
//函数参数celebrator的类型为 Name & Aged；
//这意味着它不关心参数的具体类型，只要参数符合这两个协议即可；
func wishHappyBirthday(to celebrator: Named & Aged) {
    print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(to: birthdayPerson)

9.检查协议的一致性
is  as?  as!
        let objects: [AnyObject] = [
            Circle(radius: 2.0),
            Country(area: 243_610),
            Animal(legs: 4)
        ]
        for object in objects {
            // 对迭代出的每一个元素进行检查，看它是否遵循了HasArea协议
            if let objectWithArea = object as? HasArea {
                print("面积为 \(objectWithArea.area)")
            } else {
                print("没有面积")
            }
        }

10.代理模式
//播放音乐的协议
protocol PlayMusicTools{
    func playMusic();
}

//实现协议的类
class QQMusisApp:PlayMusicTools{
    func playMusic() {
        print("播放一首美妙的音乐")
    }
}
class Person{
    var delegate:PlayMusicTools?
    func listenMusic(){
        self.delegate?.playMusic()
    }
}
//人想听音乐但是又不能自己播放，就调用了代理的方法
let person:Person = Person()
person.delegate = QQMusisApp()
person.listenMusic()

11.可选性
//1.协议CounterDataSource包含两个可选要求
@objc protocol CounterDataSource {
    @objc optional func incrementForCount(count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}

12.默认实现
//协议：一个宠物协议，定义发出声音的方法makeSound
protocol PetProtocol{
    func makeSound()
    
}
//扩展协议：提供默认方法实现
extension PetProtocol{
    func makeSound(){
        print("aaaaaa。。。。")
    }
}
class Cat:PetProtocol{
     //因为有协议扩展，已经提供了默认的方法实现；所以这里只遵循了协议
}
class Dog:PetProtocol{
    func makeSound() {
        print("汪汪汪。。。。")
    }
}
//测试代码：
let cat = Cat();
cat.makeSound();  //打印：aaaaaa。。。。
let dog = Dog();
dog.makeSound()   //打印：汪汪汪。。。。

13.添加限制条件
extension Collection where Element: Equatable {
    func allEqual() -> Bool {
        for element in self {
            if element != self.first {
                return false
            }
        }
        return true
    }
}
//如果集合中的所有元素都一致，allEqual()方法才返回 true
let equalNumbers = [100, 100, 100, 100, 100]
print(equalNumbers.allEqual())      //打印 "true"
let differentNumbers = [100, 100, 200, 100, 200]
print(differentNumbers.allEqual())  //打印 "false"


十八、范型
1.语法
func SwapTwoThing<T>(a:inout T, b:inout T){
    (a, b) = (b, a)
}
var a = 100
var b = 200
swapTwoInt(a: &a , b: &b)//用&表示可改变外部值

2.常用的范型
let arr = Array<Int>()
let dict = Dictionary<String,Int>()
let set  = Set<Float>()

3.实现一个栈结构体
struct Stack<Element>{//范型结构体
    //存放栈中变量的数组
    var items = Array<Element>()//范型变量
    
    //入栈：向栈中添加一个新元素
    mutating func push(item:Element){//范型方法
        items.append(item)
    }
    
    //出栈：删除栈顶元素,并返回此元素
    mutating func pop() ->Element?{
        return items.removeLast()
    }
}

var stack = Stack<Int>()
stack.push(item: 11)
stack.push(item: 22)
stack.pop()   //22
var stack1 = Stack<String>()
stack1.push(item:"aaa")
stack1.push(item:"bbb")
stack1.pop()  //"bbb"

4.自定义泛型类型：多个占位符
struct Pair<T1, T2>{
    var t1:T1
    var t2:T2
}
var pair1 = Pair(t1: "hello", t2: "hi")
print(pair1)   //Pair<String, String>(t1: "hello", t2: "hi")
var pair2:Pair<String, Int> = Pair(t1:"hello",t2: 123)//多类型
print(pair2)   //Pair<String, Int>(t1: "hello", t2: 123)


5.扩展
extension Stack {
    //返回当前栈顶元素而不会将其从栈中移除
    var topItem: Element? {
        return items.isEmpty ? nil : items[items.count - 1]
    }
}
var stack3 = Stack<Int>()
stack3.push(item:1)
stack3.push(item:2)
stack3.push(item: 3)
if let topItem = stack3.topItem{
    print("栈顶元素:\(topItem)")   //栈顶元素:3
}

6.约束
/协议,数值类型
func findIndex<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
    for (index, value) in array.enumerated() {
        if value == valueToFind {
            return index
        }
    }
    return nil
}
let doubleIndex = findIndex(of: 9.3, in: [3.14159, 0.1, 0.25])  //nil
let stringIndex = findIndex(of: "Andrea", in: ["Mike", "Malcolm", "Andrea"]) //2

7.关联类型
protocol WeightCaclulable{
    //associatedtype设置别名，即关联类型
    associatedtype WeightType
    var weight:WeightType{get} //返回重量属性，其类型是WeightType
}

//iphone7:手机较轻，表示重量时会有小数点，所以使用Double描述
class Iphone7:WeightCaclulable{
    //实现的时候用的是typealias
    typealias WeightType  = Double
    
    var weight: Double {
        return 0.114
    }
}
//Ship:轮船较重,表示重量可以忽略小数，所以使用Int描述
class Ship:WeightCaclulable{
    typealias WeightType = Int
    var weight: WeightType
    
    init(weight:WeightType) {
        self.weight = weight
    }
}
let iphone7 = Iphone7()
print(iphone7.weight)  //0.114
let ship = Ship(weight: 100000)
print(ship.weight)     //100000

8.关联类型添加约束
协议中存在关联类型，我们也可以为其添加约束，下面是一个Container协议，
我们设置其关联类型Item遵循了协议Equatable
protocol Container {
    associatedtype Item: Equatable
    
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}



九、控制
访问级别    定义
public  可以访问自己模块中源文件里的任何实体，别人也可以通过引入该模块来访问源文件里的所有实体。
internal    可以访问自己模块中源文件里的任何实体，但是别人不能访问该模块中源文件里的实体。
fileprivate 文件内私有，只能在当前源文件中使用。
private 只能在类中访问，离开了这个类或者结构体的作用域外面就无法访问。

1.子类的访问级别不得高于父类的访问级别
2.常量、变量、属性不能拥有比它们的类型更高的访问级别
3.常量、变量、属性、下标索引的Getters和Setters的访问级别继承自它们所属成员的访问级别。
Setter的访问级别可以低于对应的Getter的访问级别
4.





